package jpave.query_interface;

import java.awt.Component;
import java.sql.ResultSet;
import java.util.Iterator;
import java.util.Vector;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;

import util.Debug.ErrorReport;

import jpave.dataholders.ContigData;
import jpave.dataholders.MainData;

public class ContigGOPanel extends JPanel {
	private static final long serialVersionUID = 1L;

	public ContigGOPanel(JPaveFrame frame, MainData inTheCluster, String h) {
		theParentFrame = frame;
		inCluster = inTheCluster;
		theData = new Vector<TableRowData> ();
		if (h!=null) strHit = h;
		
		setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
		add(createTablePanel());
		setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
	}
	
	private JPanel createTablePanel() {
		JPanel retVal = new JPanel();
		retVal.setLayout(new BoxLayout(retVal, BoxLayout.PAGE_AXIS));
		
		theTableModel = new TableModel();
		theTable = new JTable(theTableModel);
		sPane = new JScrollPane(theTable);
		
		theTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
		retVal.add(sPane);
		
		// should only be one contigID
		Vector<String> contigIDs = new Vector<String> ();
		Iterator<ContigData> iter = inCluster.getContigIterator();
		while(iter.hasNext()) {
			contigIDs.add(iter.next().getContigID());
		}
		String contig = contigIDs.get(0);
		int DUHID=0;
		ResultSet rs;
		String strQuery;
		String name;
		
		try {
			if (strHit!=null) { // all GOs for unitran
				rs = theParentFrame.doQuery("Select DUHID from pja_db_unique_hits " +
						"where hitID='" + strHit + "'");
				if (rs.next()) DUHID=rs.getInt(1);
				strQuery = "SELECT pja_gotree.gonum, pja_gotree.level, pja_gotree.name " + 
						  "FROM  pja_uniprot_go " +  
						  "JOIN  pja_gotree ON pja_gotree.gonum = pja_uniprot_go.gonum " + 
						  "WHERE pja_uniprot_go.DUHID = " + DUHID + 	" " + 		
						  "ORDER BY pja_gotree.tblidx";
				name = strHit;
			}
			else { // all GOs for contig
				strQuery = "SELECT pja_gotree.gonum, pja_gotree.level, pja_gotree.name " + 
						  "FROM pja_unitrans_go " + 
						  "JOIN contig ON contig.CTGID = pja_unitrans_go.CTGID " + 
						  "JOIN pja_gotree ON pja_gotree.gonum = pja_unitrans_go.gonum " + 
						  "WHERE contig.contigid = '" + contig + "'" + 			
						  "ORDER BY pja_gotree.tblidx";
				name = contig;
			}
			
			rs = theParentFrame.doQuery(strQuery);
			while(rs.next()) {
				theData.add(new TableRowData(name, rs.getString(3), 
						rs.getInt(2), rs.getLong(1)));
				if(nMinLevel < 0 || theData.get(theData.size()-1).getLevel() < nMinLevel)
					nMinLevel = theData.get(theData.size()-1).getLevel();
				if(nMaxLevel < 0 || theData.get(theData.size()-1).getLevel() > nMaxLevel)
					nMaxLevel = theData.get(theData.size()-1).getLevel();
			}
			rs.close();
			theTableModel.fireTableStructureChanged();
			theTableModel.fireTableDataChanged();
			autofitColumns();
		}
		catch(Exception e) {
			ErrorReport.reportError(e, "Generating GO table");
		}
		
		return retVal;
	}
	
	private Vector<TableRowData> theData = null;
	private JTable theTable = null;
	private TableModel theTableModel = null;
	private JScrollPane sPane = null;
	private String strHit = null;
	
	private JPaveFrame theParentFrame = null;
	private MainData inCluster = null;
	private int nMinLevel = -1;
	private int nMaxLevel = -1;
	
	private class TableModel extends AbstractTableModel {
		private static final long serialVersionUID = 1L;

		public int getColumnCount() {
			return nMaxLevel - nMinLevel + 3;
		}

		public String getColumnName(int colIndex) {
			if(colIndex == 0)
				return "Description";
			if(colIndex == getColumnCount()-1)
				return "ID";
			return "Level " + (nMinLevel + (colIndex));
		}
		public int getRowCount() {
			return theData.size();
		}

		public Object getValueAt(int row, int col) {
			if(col == 0)
				return theData.get(row).getDescription();
			if(col == getColumnCount()-1)
				return theData.get(row).getContigID();
			if(col == (theData.get(row).getLevel()+1))
				return "GO:" + String.format("%08d", theData.get(row).getID());
			return null;
		}	
	}
	
	private class TableRowData {
		public TableRowData(String contigID, String description, int level, long gonum) {
			strContigID = contigID;
			strDescription = description;
			nLevel = level;
			nGoNum = gonum;
		}
		public String getContigID() { return strContigID; }
		public String getDescription() { return strDescription; }
		public int getLevel() { return nLevel; }
		public long getID() { return nGoNum; }
		
		private String strContigID = "";
		private String strDescription = "";
		private int nLevel = -1;
		private long nGoNum = -1;
	}
	
    private void autofitColumns() {
        TableColumn column;
        Component comp;
        int headerWidth;
        int cellWidth;
        TableCellRenderer headerRenderer = theTable.getTableHeader().getDefaultRenderer();
        
        for (int i = 0;  i < theTable.getColumnCount();  i++) { // for each column
            column = theTable.getColumn(theTable.getColumnName(i));

            comp = headerRenderer.getTableCellRendererComponent(
            					theTable, column.getHeaderValue(),
                                 false, false, 0, i);
            
            headerWidth = comp.getPreferredSize().width + 10; // why +10 ???
            
            cellWidth = 0;
            for (int j = 0;  j < theTable.getRowCount();  j++) { // for each row
	            comp = theTable.getDefaultRenderer(theTable.getColumnClass(i)).
	            			getTableCellRendererComponent(
	                                 theTable, theTable.getValueAt(j, i),
	                                 false, false, j, i);
	            cellWidth = Math.max(cellWidth, comp.getPreferredSize().width + 10);
	            if (j > 100) break; // only check beginning rows, for performance reasons
            }

            column.setPreferredWidth(Math.max(headerWidth, cellWidth));
        }
    }

}
